package com.dawn.module.hospital.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dawn.framework.common.pojo.CommonResult;
import com.dawn.framework.common.util.http.HttpUtils;
import com.dawn.framework.common.util.string.StrUtils;
import com.dawn.framework.web.core.util.RequestUtils;
import com.dawn.framework.web.core.util.WebFrameworkUtils;
import com.dawn.module.hospital.controller.app.chs.vo.ChsOrderHisFeeReqVO;
import com.dawn.module.hospital.controller.app.chs.vo.ChsOrderUnifiedReqVO;
import com.dawn.module.hospital.dal.dataobject.chs.config.ChsConfigDO;
import com.dawn.module.hospital.enums.BHConstants;
import com.dawn.module.hospital.model.pay.PayOrderCreateResModel;
import com.dawn.module.hospital.service.chs.config.ChsConfigService;
import com.dawn.module.hospital.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.dawn.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.dawn.module.hospital.enums.ErrorCodeConstants.CHS_CONFIG_NOT_EXISTS;

/**
 * @description:
 * @author: cnsu-cmh
 * @time: 2024/8/8 18:06
 */
@Slf4j
@Service
public class ChsOrderService extends BHService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ChsConfigService chsConfigService;

    public CommonResult hisChsFee(ChsOrderHisFeeReqVO reqVO) {
        ChsConfigDO chsConfigDO = chsConfigService.getChsConfig();
        if (chsConfigDO.getId() == null) {
            throw exception(CHS_CONFIG_NOT_EXISTS);
        }

//        Map requestBody = new HashMap<String,String>();
//        requestBody.put("BRID",patientId);
//        requestBody.put("SFGH",sfgh);
//        requestBody.put("XL",450);
//        requestBody.put("medOrgOrd",medOrgOrd);
//        requestBody.put("idNo",idCardNo);
//        requestBody.put("username",patientName);
//        requestBody.put("payAuthNo",payAuthNo);
//        requestBody.put("uldLatlnt",uldLatlnt);
//        requestBody.put("JSKLB", UserConstants.JSKLB_WEIXIN_SERVICE_ACCOUNTS_CHS);

        JSONObject requestBody = new JSONObject();
        requestBody.put("BRID",reqVO.getPatientId());
        requestBody.put("SFGH",reqVO.getSfgh());
        requestBody.put("XL",450);
        requestBody.put("medOrgOrd",reqVO.getMedOrgOrd());
        requestBody.put("idNo",reqVO.getIdCardNo());
        requestBody.put("username",reqVO.getPatientName());
        requestBody.put("payAuthNo",reqVO.getPayAuthNo());
        requestBody.put("uldLatlnt",reqVO.getUldLatlnt());
        String chsHisFeeUrl = chsConfigDO.getHisOrderUrl();
        if(BHConstants.WEIXIN_SERVICE_ACCOUNTS.getCode().equals(reqVO.getAppType())) {
            requestBody.put("JSKLB", BHConstants.PAY_CARD_WX_CHS_HIS);
//            chsHisFeeUrl =  getHisWxChsServerUri() + BHConstants.CHS_HIS_FEE.getValue();

        }
        if (BHConstants.ALIPAY_MINI_APPLET.getCode().equals(reqVO.getAppType())) {
            requestBody.put("JSKLB", BHConstants.PAY_CARD_ALI_CHS_HIS);
//             chsHisFeeUrl =  getHisAliChsServerUri() + BHConstants.CHS_HIS_FEE.getValue();
        }

//        requestBody.put("chsHisFeeUrl", chsHisFeeUrl);
        log.info("HisChsOrderUrl =" + chsHisFeeUrl);
        log.info("requestBody =" + JSON.toJSONString(requestBody));
        String rspStr = HttpUtils.postJsonStr(chsHisFeeUrl, requestBody);
        log.info("rspStr =" + rspStr);
        JSONObject apiResult = JSONObject.parseObject(rspStr);
        if("0".equals(apiResult.getString("code"))) {
            String message = apiResult.getString("msg");
            return CommonResult.error(ERROR_CODE,message);
        }
//        JSONObject rsp = apiResult.getJSONObject("data");


        Map map = new HashMap();
        map.put("medOrgOrd",reqVO.getMedOrgOrd());
        map.put("idNo",reqVO.getIdCardNo());
        map.put("username",reqVO.getPatientName());

//        apiResult.remove("extData");
//        JSONObject orderInfo = apiResult;
        map.put("orderInfo",apiResult);
        map.putAll(requestBody);
        return CommonResult.success(map);
    }

    public CommonResult wxPay(ChsOrderUnifiedReqVO reqVO) {
        String orderNumber = reqVO.getOrderNumber();
        Object orderObj = stringRedisTemplate.opsForValue().get("CHSPayOrder_" + orderNumber);
        if(orderObj != null) {
            String cacheOrderData = orderObj.toString();
            if (!StringUtils.isEmpty(cacheOrderData)) {
                JSONObject prePayInfo = JSON.parseObject(cacheOrderData);
                return CommonResult.success(prePayInfo);
            }
        }

        String orderType = reqVO.getOrderType();

        String patientId = reqVO.getPatientId();
        // totalFee
        String totalFee = reqVO.getTotalFee();
        // cashFee
        String cashFee = reqVO.getCashFee();
        // psnAcctPay
        String psnAcctPay = reqVO.getPsnAcctPay();
        //fundPay
        String fundPay = reqVO.getFundPay();
        String serialNo = reqVO.getMedOrgOrd();
        // payAuthNo
        String payAuthNo = reqVO.getPayAuthNo();
        // payOrdId
        String payOrdId = reqVO.getPayOrdId();
        // uldLatlnt
        String uldLatlnt = reqVO.getUldLatlnt();
        // idNo
        String userCardNo = reqVO.getIdNo();
        // username
        String userName = reqVO.getUsername();

        String payOrderType = getChsOrderType(orderNumber);
        String insuranceFee = getInsuranceFee(psnAcctPay,fundPay);
        Integer payType = getChsPayType(cashFee);

        HttpServletRequest request = WebFrameworkUtils.getRequest();
        String spbillCreateIp = RequestUtils.getClientIp(request);
        String gmtOutCreate = DateUtils.getDate("yyyyMMddHHmmss");
        /**
         * {"payAuthNo":"AUTH****","payOrdId":"ORD****","setlLatlnt":"118.096435,24.485407"}
         */
        JSONObject requestContentJson = new JSONObject();
        requestContentJson.put("payAuthNo",payAuthNo);
        requestContentJson.put("payOrdId",payOrdId);
        requestContentJson.put("setlLatlnt",uldLatlnt);
        String requestContent = requestContentJson.toJSONString();
        /**
         * 是否允许预结算费用发生变化
         * 0：不允许
         * 1：允许
         * 当医保局返回的预结算金额与医院上传的金额不一致时，此字段为0则直接报错，为1则以医保局金额为准
         */
        int allowFeeChange = 0;


        String isDept = "4";
        String orderName = "";
        if("REG".equals(orderType)) {
            orderName = "预约挂号";
        }
        if("RECIPE".equals(orderType)) {
            orderName = "门诊缴费";
        }
        if("PRE_PAYMENT".equals(orderType)) {
            orderName = "住院预交";
        }

        HashMap<String,Object> chsParams = new HashMap();
        chsParams.put("orderType",payOrderType);
        chsParams.put("totalFee",totalFee);
        chsParams.put("cashFee",cashFee);
        chsParams.put("insuranceFee",insuranceFee);
        chsParams.put("payType",payType);
        chsParams.put("serialNo",serialNo);
        chsParams.put("gmtOutCreate",gmtOutCreate);
        chsParams.put("requestContent",requestContent);
        chsParams.put("allowFeeChange",allowFeeChange);
        chsParams.put("userCardNo",userCardNo);
        chsParams.put("userName",userName);
        chsParams.put("isDept",isDept);
        chsParams.put("spbillCreateIp",spbillCreateIp);
        chsParams.put("payAuthNo",payAuthNo);
        chsParams.put("payOrdId",payOrdId);

        String acctFee = new BigDecimal(psnAcctPay.trim()).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        String fundFee = new BigDecimal(fundPay.trim()).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        chsParams.put("acctFee",acctFee);
        chsParams.put("fundFee",fundFee);

        if(StringUtils.hasText(reqVO.getBillNo())) {
            chsParams.put("billNo",reqVO.getBillNo());
        }
        if(StringUtils.hasText(reqVO.getBillNos())) {
            chsParams.put("billNos",reqVO.getBillNos());
        }

        BigDecimal totalCostB = new BigDecimal(totalFee);
        String body = CDBPayUtils.packageBody(patientId,userName,
                StrUtils.getStringValue(reqVO.getClinicNo()),
                StrUtils.getStringValue(userCardNo),
                StrUtils.getStringValue(serialNo));


        CommonResult payResult = CDBPayUtils.instance().build(CDBPayUtils.WX_CHS)
                .wxChsJsapiPay(orderNumber, BHConstants.WEIXIN_SERVICE_ACCOUNTS.getMsg()  + "-" + orderName + "-医保移动支付",
                        totalCostB.setScale(2, BigDecimal.ROUND_HALF_UP).toString(),
                        body, reqVO.getUserId(), chsParams);

        if(payResult.isError()) {
            return payResult;
        }
        JSONObject resData = (JSONObject)payResult.getData();
        PayOrderCreateResModel res = JSONObject.toJavaObject(resData,PayOrderCreateResModel.class);
        String payDataStr = res.getPayData();
        stringRedisTemplate.opsForValue().set("CHSPayOrder_"+orderNumber,payDataStr,30L, TimeUnit.MINUTES);

        JSONObject prePayInfo = JSON.parseObject(payDataStr);
        return CommonResult.success(prePayInfo);
    }

    private String getChsOrderType(String orderNumber) {
        /**
         * RegPay=挂号支付
         * DiagPay=诊间支付
         * CovidExamPay=新冠检测费用（核酸）
         * InHospPay=住院费支付
         * PharmacyPay=药店支付
         * InsurancePay=保险费支付
         * IntRegPay=互联网医院挂号支付
         * IntReDiagPay=互联网医院复诊支付
         * IntPscPay=互联网医院处方支付
         * CvidAntigenPay=新冠抗原检测
         */
        String orderType = "DiagPay";

        if (orderNumber.indexOf("GH") != -1) {
            orderType = "RegPay";
        } else if (orderNumber.indexOf("JF") != -1 || orderNumber.indexOf("QR") != -1) {
            orderType = "DiagPay";
        } else if (orderNumber.indexOf("NAT") != -1) {
            orderType = "CovidExamPay";
        }
        return orderType;
    }

    private String getInsuranceFee(String psnAcctPay, String fundPay) {
        BigDecimal insuranceFeeB  = new BigDecimal(psnAcctPay.trim()).add(new BigDecimal(fundPay.trim()));
        if(insuranceFeeB.compareTo(new BigDecimal(0)) == 0) {
            return "0";
        }
        String insuranceFee = insuranceFeeB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        return insuranceFee;
    }

    private Integer getChsPayType(String cashFee) {
        /**
         * 1：现金 2：医保 3：现金+医保
         * 备注说明：
         * 1、当订单要走医保支付时，
         * （1）cash_fee>0, paytype填3
         * （2）cash_fee=0, paytype填2
         * 2、当订单不使用医保支付时 paytype填1。
         * 3、当订单有走医保【6201】相关接口时，即使订单为纯自费订单，paytype填3。
         */
        int compare = new BigDecimal(cashFee.trim()).compareTo(new BigDecimal(0));
        if(compare == 0) {
            return 2;
        }
        return 3;
    }

    public CommonResult aliMiniPay(ChsOrderUnifiedReqVO reqVO) {
        return CommonResult.success(reqVO);
    }

    public JSONObject chsPayHis(String patientId, int sfgh, String amount, String mchOrderNo, JSONObject chsOrder) {
        JSONObject requestBody = new JSONObject();
        requestBody.put("BRID",patientId);
        requestBody.put("SFGH",sfgh);
        requestBody.put("XL",450);
        requestBody.put("JE",amount);
        requestBody.put("medOrgOrd",chsOrder.getString("billNos"));
        requestBody.put("idNo",chsOrder.getString("userCardNo"));
        requestBody.put("payAuthNo",chsOrder.getString("payAuthNo"));
        requestBody.put("payOrdId",chsOrder.getString("payOrdId"));
        requestBody.put("CZLX",0);
        requestBody.put("JYLSH",mchOrderNo);
        requestBody.put("JSKLB", BHConstants.PAY_CARD_WX_CHS_HIS);
        requestBody.put("JYSM", "医保移动支付-微信");
        requestBody.put("JSFS", BHConstants.PAY_CARD_WX_CHS_HIS);

        Long cashFeeL = chsOrder.getLong("cashFee");
        if(cashFeeL.compareTo(new Long(0)) == 0) {
            requestBody.put("JSJE", 0);
        } else {
            BigDecimal cashFeeB = new BigDecimal(cashFeeL).divide(new BigDecimal(100));
            String cashFee = cashFeeB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            requestBody.put("JSJE", cashFee);
        }

        ChsConfigDO chsConfigDO = chsConfigService.getChsConfig();
        String chsHisConfirmUrl = chsConfigDO.getHisConfirmUrl();
//        if(BHConstants.WEIXIN_SERVICE_ACCOUNTS.getCode().equals(reqVO.getAppType())) {
//            requestBody.put("JSKLB", CS.PAY_CARD_ALI_CHS_HIS);
//            requestBody.put("JYSM", "医保移动支付-支付宝");
//            requestBody.put("JSFS", CS.PAY_CARD_ALI_CHS_HIS);
//
//        }
//        if (BHConstants.ALIPAY_MINI_APPLET.getCode().equals(reqVO.getAppType())) {
//            requestBody.put("JSKLB", BHConstants.PAY_CARD_WX_CHS_HIS);
//            requestBody.put("JYSM", "医保移动支付-微信");
//            requestBody.put("JSFS", BHConstants.PAY_CARD_WX_CHS_HIS);
//        }

        log.info("chsHisConfirmUrl =" + chsHisConfirmUrl);
        log.info("requestBody =" + JSON.toJSONString(requestBody));

        String rspStr = HttpUtils.postJsonStr(chsHisConfirmUrl, requestBody);
//        String rspStr = "{\"code\":\"1\",\"msg\":\"成功\",\"CZSJ\":\"2023-01-10 17:37:16\",\"JZID\":\"917604\",\"KPBZ\":\"0\",\"URL\":null,\"NETURL\":null,\"FPTT\":\"杨玉华\",\"FPH\":null,\"FPJE\":\"0\",\"KPRQ\":null}";
        log.info("rspStr =" + rspStr);

        JSONObject rsp = JSONObject.parseObject(rspStr);
        log.info("rsp =" + rsp.toJSONString());
        return rsp;
    }

    public JSONObject chsPayRefundHis(String patientId, int sfgh, String amount, String mchOrderNo, String refundReason,JSONObject chsOrder) {
        JSONObject requestBody = new JSONObject();
        requestBody.put("BRID",patientId);
        requestBody.put("SFGH",sfgh);
        requestBody.put("XL",450);
        requestBody.put("JE",amount);
        requestBody.put("medOrgOrd",chsOrder.getString("billNos"));
        requestBody.put("idNo",chsOrder.getString("userCardNo"));
        requestBody.put("payAuthNo",chsOrder.getString("payAuthNo"));
        requestBody.put("payOrdId",chsOrder.getString("payOrdId"));
        requestBody.put("CZLX",0);
        requestBody.put("JYLSH",mchOrderNo);
        requestBody.put("JSKLB", BHConstants.PAY_CARD_WX_CHS_HIS);
        requestBody.put("JYSM", refundReason);
        requestBody.put("JSFS", BHConstants.PAY_CARD_WX_CHS_HIS);

        Long cashFeeL = chsOrder.getLong("cashFee");
        if(cashFeeL.compareTo(0L) == 0) {
            requestBody.put("JSJE", 0);
        } else {
            BigDecimal cashFeeB = new BigDecimal(cashFeeL).divide(new BigDecimal(100));
            String cashFee = cashFeeB.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            requestBody.put("JSJE", cashFee);
        }

        ChsConfigDO chsConfigDO = chsConfigService.getChsConfig();
        String chsHisRefundUrl = chsConfigDO.getHisRefundUrl();

//        String payRefundUrl = getHisWxChsServerUri() + BHConstants.CHS_HIS_FEE.getValue();
        log.info("PayRefundUrl =" + chsHisRefundUrl);
        log.info("requestBody =" + JSON.toJSONString(requestBody));

        String rspStr = HttpUtils.postJsonStr(chsHisRefundUrl, requestBody);
        log.info("rspStr =" + rspStr);

        JSONObject rsp = JSON.parseObject(rspStr);
        log.info("rsp =" + rsp.toJSONString());
        return rsp;
    }
}
